#pragma once
#include "../Utilities/matrix.h"
#include "stdafx.h"
#include "../Utilities/image.h"
#include <cstdio>
#include <ctime>
using namespace std;

class Fractals
{
public:
	Fractals(int);
	~Fractals();
	void ReadFractals(char*);
	void WriteImage(char*);

protected:
private:
	int _n;		// number of transformations
	Matrix* _m; // array of matrix
	float* _p;	// probabilities for choosing a transformation

	int _l;		// image length;
};

Fractals::Fractals(int length = 400) : _l(length / 2){}

Fractals::~Fractals()
{
	delete [] _m;
	delete [] _p;
}
void Fractals::ReadFractals(char* filename)
{
	FILE *input = fopen(filename,"r");
	assert(input != NULL);

	fscanf(input,"%d",&_n);

	_m = new Matrix[_n];

	_p = new float[_n];

	for (int i = 0; i < _n; i++) {
		fscanf (input,"%f",&_p[i]);
		assert (input != NULL);
		Clear();
		for (int y = 0; y < 4; y++) {
			if (y == 2) continue;
			for (int x = 0; x < 4; x++) {
				if (x == 2) continue;
				float data;
				int scanned = fscanf (input,"%f", data);
				_m->Set(x, y, data);
				assert (scanned == 1); } } }
	}

	for (int i =  _n - 1; i > 0; i--)
		for(int j = 0; j < i; j++)
			_p[i] += _p[j];

	fclose(input);
}

void Fractals::WriteImage(char* filename)
{
	srand((unsigned)time(0));

	Image img(_l * 2, _l * 2);
	Vec3f white(255.0, 255.0, 255.0);
	img.SetAllPixels(white);
	Matrix po;

	for(int i = 0; i < 100000; i++)
	{
		po.Set(0, 0, float(rand() % _l));
		po.Set(0, 1, float(rand() % _l));
		po.Set(0, 3, (float)_l);

		int fi;
		for(int k = 0; k < 100; k++)
		{
			float x = float(rand() % 100) / 100;

			for(int n = 0; n < _n; n++)
			{
				if ( x < _p[n])
				{
					fi = n;
					break;
				}
			}
			po = _m[fi] * po;
		}
		//Vec3f v(po.Get(0, 0), po.Get(0, 1), po.Get(0, 3));
		Vec3f v(0.0, 255.0, 0.0);
		img.SetPixel((int)po.Get(0, 0) + _l / 2, (int)po.Get(0, 1) + _l, v);
	}


	img.SaveTGA(filename);
}